﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ComponentFactory.Krypton.Toolkit;
using StableDiffusionTools.Controls;
using StableDiffusionTools.Imaging;
using StableDiffusionTools.Utils;

namespace StableDiffusionTools.Forms
{
    public partial class HSLColorPickerForm : KryptonForm
    {
        private bool hslIgnore = false;
        private bool colorIgnore = false;

        private bool useAlpha = true;
        public bool UseAlpha
        {
            get { return useAlpha; }
            set
            {
                if(useAlpha != value)
                {
                    colorPreview.UseAlpha = kryptonNUDAlpha.Enabled = useAlpha = value;
                }
            }
        }

        public HSLColorPickerForm()
        {
            //SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
            InitializeComponent();

            KeyDown += (s, e) =>
            {
                if(e.KeyCode == Keys.Escape)
                {
                    DialogResult = DialogResult.Cancel;
                }
            };

            StartPosition = FormStartPosition.CenterParent;

            //hslColorPicker1.BackColor = BackColor;
        }

        private void OnPalettePaint(object sender, PaletteLayoutEventArgs e)
        {
            Invalidate();
        }

        private void OnGlobalPaletteChanged(object sender, EventArgs e)
        {
            //hslColorPicker1.BackColor = BackColor;

            Invalidate();
        }

        public DialogResult ShowDialog(ColorHSL colorHSL)
        {
            hslColorPicker1.SetHSL(colorHSL);
            return base.ShowDialog();
        }

        public DialogResult ShowDialog(Color color)
        {
            return ShowDialog(ColorHSL.FromColor(color));
        }

        public DialogResult ShowDialog(ColorHSL colorHSL, IWin32Window window)
        {
            hslColorPicker1.SetHSL(colorHSL);
            return base.ShowDialog(window);
        }

        public DialogResult ShowDialog(Color color, IWin32Window window)
        {
            return ShowDialog(ColorHSL.FromColor(color), window);
        }

        public ColorHSL GetHSL() { return hslColorPicker1.GetHSL(); }

        private void hslColorPicker1_ValueChanged(object sender, EventArgs e)
        {
            ColorHSL hsl = hslColorPicker1.GetHSL();
            Color color = hsl.ToColor();
            if (!hslIgnore)
            {
                hslIgnore = true;
                kryptonNUDHue.Value = (decimal)hsl.H < 0.01m ? 1.0m : (decimal)hsl.H;
                kryptonNUDSat.Value = (decimal)hsl.S;
                kryptonNUDLum.Value = (decimal)hsl.L;
                hslIgnore = false;
            }
            if (!colorIgnore)
            {
                colorIgnore = true;
                kryptonNUDRed.Value = color.R;
                kryptonNUDGreen.Value = color.G;
                kryptonNUDBlue.Value = color.B;
                kryptonNUDAlpha.Value = color.A;
                colorIgnore = false;
            }
            kryptonTBHex.Text = useAlpha ? ImageUtil.ColorToHexARGB(color) : ImageUtil.ColorToHexRGB(color);
            kryptonTBBGRA.Text = $"{(useAlpha ? color : Color.FromArgb(0, color)).ToArgb()}";
            colorPreview.Color = color;
        }

        private void kryptonNUDHue_ValueChanged(object sender, EventArgs e)
        {
            if (hslIgnore)
                return;

            hslIgnore = true;
            ColorHSL hsl = hslColorPicker1.GetHSL();
            hsl.H = (double)((KryptonNumericUpDown)sender).Value;
            hslColorPicker1.SetHSL(hsl);
            hslIgnore = false;
        }

        private void kryptonNUDSat_ValueChanged(object sender, EventArgs e)
        {
            if (hslIgnore)
                return;

            hslIgnore = true;
            ColorHSL hsl = hslColorPicker1.GetHSL();
            hsl.S = (double)((KryptonNumericUpDown)sender).Value;
            hslColorPicker1.SetHSL(hsl);
            hslIgnore = false;
        }

        private void kryptonNUDLum_ValueChanged(object sender, EventArgs e)
        {
            if (hslIgnore)
                return;

            hslIgnore = true;
            ColorHSL hsl = hslColorPicker1.GetHSL();
            hsl.L = (double)((KryptonNumericUpDown)sender).Value;
            hslColorPicker1.SetHSL(hsl);
            hslIgnore = false;
        }

        private void kryptonNUDRed_ValueChanged(object sender, EventArgs e)
        {
            if (colorIgnore)
                return;

            colorIgnore = true;
            Color oldC = hslColorPicker1.GetHSL().ToColor();
            Color newC = Color.FromArgb(oldC.A, (int)((KryptonNumericUpDown)sender).Value, oldC.G, oldC.B);
            hslColorPicker1.SetHSL(ColorHSL.FromColor(newC));
            colorIgnore = false;
        }

        private void kryptonNUDGreen_ValueChanged(object sender, EventArgs e)
        {
            if (colorIgnore)
                return;

            colorIgnore = true;
            Color oldC = hslColorPicker1.GetHSL().ToColor();
            Color newC = Color.FromArgb(oldC.A, oldC.R, (int)((KryptonNumericUpDown)sender).Value, oldC.B);
            hslColorPicker1.SetHSL(ColorHSL.FromColor(newC));
            colorIgnore = false;
        }

        private void kryptonNUDBlue_ValueChanged(object sender, EventArgs e)
        {
            if (colorIgnore)
                return;

            colorIgnore = true;
            Color oldC = hslColorPicker1.GetHSL().ToColor();
            Color newC = Color.FromArgb(oldC.A, oldC.R, oldC.G, (int)((KryptonNumericUpDown)sender).Value);
            hslColorPicker1.SetHSL(ColorHSL.FromColor(newC));
            colorIgnore = false;
        }

        private void kryptonNUDAlpha_ValueChanged(object sender, EventArgs e)
        {
            if (colorIgnore)
                return;

            colorIgnore = true;
            Color oldC = hslColorPicker1.GetHSL().ToColor();
            Color newC = Color.FromArgb((int)((KryptonNumericUpDown)sender).Value, oldC.R, oldC.G, oldC.B);
            hslColorPicker1.SetHSL(ColorHSL.FromColor(newC));
            colorIgnore = false;
        }

        private void kryptonTBBGRA_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                //load BGRA and apply
                try
                {
                    if (int.TryParse(kryptonTBBGRA.Text, out int result))
                    {
                        Color color = Color.FromArgb(result);
                        if (!useAlpha && color.A != 0)
                        {
                            color = Color.FromArgb(0, color.R, color.G, color.B);
                            kryptonTBBGRA.Text = $"{color.ToArgb()}";
                        }
                        hslColorPicker1.SetHSL(ColorHSL.FromColor(color));
                        e.SuppressKeyPress = true;
                    }
                }
                catch (Exception) { } //Ignore (and play beep)
            }
        }

        private void kryptonTBHex_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                //load hex and apply
                try
                {
                    Color color = ColorTranslator.FromHtml(kryptonTBHex.Text);
                    if (!useAlpha && color.A != 0)
                    {
                        color = Color.FromArgb(0, color.R, color.G, color.B);
                        kryptonTBHex.Text = ImageUtil.ColorToHexRGB(color);
                    }
                    hslColorPicker1.SetHSL(ColorHSL.FromColor(color));
                    e.SuppressKeyPress = true;
                }
                catch (Exception) { } //Ignore (and play beep)
            }
        }

        [Obsolete("This is not supported in this class.", true)]
        public new void Show(IWin32Window window) { }
        [Obsolete("This is not supported in this class.", true)]
        public new void Show() { }
    }
}
